<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>构造函数的回顾</title>
</head>

<body>
    <script>

        /* 
            new Person的时候，构造函数会创建一个空对象，并把this指向该对象
            然后把属性添加到该对象后，默认返回this出去
            this其实就是实例对象
            假如构造函数手写一个return ，返回的值是一个对象时，会覆盖实例对象
            假如返回的不是对象，就不会覆盖
         */


        /* 
            1:创建构造
         */
        function Person1(name, age) {
            // 把name,age加到实例上，只有实例可以访问
            this.name = name
            this.age = age
            this.say = function () {
                console.log('执行函数');
            }

        }
        let p1 = new Person1('zs', 18)
        console.log(p1);

        /* 
        
            2：构造函数继承
            继承父类的构造
            父类公共的方法写在构造函数内，这样导致每一个实例对象上都有，体积比较大
         */
        function Person2(name, age) {
            // 把name,age加到实例上，只有实例可以访问
            this.name = name
            this.age = age
            this.say = function () {
                console.log('执行函数');
            }
        }
        function Student1(name, age, sex) {
            // 使用构造函数继承，来继承属性
            Person2.call(this, name, age)
            this.sex = sex
        }



        let student1 = new Student1('ls', 18, '男')
        console.log('student1=', student1);

        /* 
            3：原型继承
            把父类公共的方法写到，原型上
            子类通过原型继承父类的实例，可以获得父类原型上的方法
         */


        function Person3(name, age) {
            this.name = name
            this.age = age
        }
        Person3.prototype.say = function () {
            console.log('执行函数');
        }
        function Student2(name, age, sex) {
            Person3.call(this, name, age)
            this.sex = sex
        }
        // 除了要继承属性，还要继承方法(父类原型上的方法)，继承方法，主要使用原型继承
        Student2.prototype = new Person3()
        let student2 = new Student2('ls', 18, '男')
        console.log('student2=', student2);

        /* 
            4：class是es6新增的语法糖（构造函数和继承）
         */
        class Person4 {
            constructor(name, age) {
                // 属性加到实例上
                this.name = name
                this.age = age
            }

            // 方法加到原型上
            say() {
                console.log('函数执行了');
            }
        }

        class Student3 extends Person4 {
            constructor(name, age, sex) {
                // super指向的是Person4的constructor函数
                super(name, age)
                this.sex = sex
            }
        }

        let student3 = new Student3('张三', 18, '男')
        console.log('student3=', student3);

        /* 
            class的注意点
         */

        //  手写 constructor
        class Person5 {
            constructor(name, age) {
                // 属性添加到实例上
                this.name = name
                this.age = age
            }
            // 给实例添加属性的简写形式,简写形式无法传参数
            sorce = 20
            // 方法加到原型上
            say() {
                console.log("执行函数say");
            }

            // 这种方式是把方法加到实例上
            hello = () => {
                console.log("执行函数hello");
            }
        }

        class Student4 extends Person5 {
            // 也可以不手写constructor
        }


        let student4 = new Student4('zs', 18)
        console.log('student4=', student4);
    </script>
</body>

</html>